from pythonds.basic.queue import Queue
import random


class Printer:
    def __init__(self, ppm):
        self.pagerate = ppm  # 打印速度
        self.currentTask = None  # 是否有打印任务
        self.timeRemaining = 0  # 任务剩余时间

    def tick(self):  # 模拟打印机每过 1 秒的行为
        if self.currentTask != None:
            self.timeRemaining -= 1  # 有打印任务，就将剩余时间减 1
            if self.timeRemaining <= 0:
                self.currentTask = None

    def busy(self):  # 判断打印机是否忙碌
        if self.currentTask != None:
            return True
        else:
            return False

    def startNext(self, newtask):  # 开始一个新的打印任务
        # 将当前任务设置为新任务newtask，然后根据新任务的页数和打印机的速度计算出剩余时间。
        self.currentTask = newtask
        self.timeRemaining = newtask.getPages() * 60 / self.pagerate


class Task:
    def __init__(self, time):
        self.timestamp = time  # 任务生成的时间戳
        self.pages = random.randrange(1, 21)  # 打印页数

    def getStamp(self):  # 返回任务的时间戳。
        return self.timestamp

    def getPages(self):  # 返回任务的打印页数。

        return self.pages

    def waitTime(self, currenttime):  # 计算任务的等待时间，即当前时间减去任务生成的时间戳。
        return currenttime - self.timestamp


def newPrintTask():  #是否生成新的打印任务
    num = random.randrange(1, 181)  # 180 分之1 生成作业
    if num == 180:
        return True
    else:
        return False


def simulation(numSeconds, pagesPerMinute):  # 接收两个参数numSeconds表示模拟的总时间，pagesPerMinute表示打印机的速度
    labprinter = Printer(pagesPerMinute)  # 打印机对象
    printQueue = Queue()  # 打印任务队列
    waitingtimes = []  # 存储任务等待时间的列表
    # 时间流逝
    for currentSecond in range(numSeconds):
        if newPrintTask():
            # 如果调用newPrintTask函数返回True，表示生成了新的打印任务，就创建一个任务对象task并将其加入打印队列。
            task = Task(currentSecond)
            printQueue.enqueue(task)
        if (not labprinter.busy()) and (not printQueue.isEmpty()):
            # 如果打印机不忙碌且打印队列不为空，就从队列中取出一个任务nexttask，将其等待时间加入等待时间列表，然后让打印机开始这个任务。
            nexttask = printQueue.dequeue()
            waitingtimes.append(nexttask.waitTime(currentSecond))
            labprinter.startNext(nexttask)
        labprinter.tick()  # 调用打印机的tick方法，模拟打印机过了 1 秒。
    # 计算任务的平均等待时间，并打印出平均等待时间和打印队列中未处理的任务数量。
    averageWait = sum(waitingtimes) / len(waitingtimes)
    print("平均等待时间为 %6.2f 秒，%3d 个任务未处理" % (averageWait, printQueue.size()))


for i in range(10):
    simulation(3600, 10)
